//
// Created by 15229 on 2022/11/19.
//

#include <stdio.h>

#include <pthread.h>
#include <string>
#include <semaphore.h>
#include <cstdint>
#include <thread>
#include <map>
#include <vector>


#include "SyncUtils.h"

int main() {
    uint32_t checkThreadNum = 7;
    BlockBarrier barrier(checkThreadNum);
    StateBarrier stateBarrier(checkThreadNum);

    volatile bool exit = false;

    auto threadFunc = [&](){
        int frameNum = 0;
        auto tid = std::this_thread::get_id();

        stateBarrier.init();
        barrier.await("Enter thread");
        // barrier.setEnable(false);

        while (true) {
            frameNum++;

            char what[1024];
            sprintf(what, "Thread [%d], frameNum= %d", tid, frameNum);
            int64_t sleep = [tid]()->int64_t {
                srand((unsigned)time(nullptr));
                return (rand() % (100-0+1))+ 0;
            }();
            std::this_thread::sleep_for(std::chrono::milliseconds(sleep));
            printf("%s\n", what);

            if (stateBarrier.check()) {
                break;
            }

            barrier.await(what);

            if (exit) {
                stateBarrier.mark();
            }
        }

        printf("[thread %d] Exit!!! \n\n\n", tid);

    };


    std::vector<std::thread*> mThreads;
    for (int i = 0; i < checkThreadNum; ++i) {
        auto t = new std::thread(threadFunc);
        mThreads.push_back(t);
    }


    std::thread exitMark([&exit](){
        std::this_thread::sleep_for(std::chrono::milliseconds(10000));
        printf("############### EXIT!!! #############################\n");
        exit = true;
    });
    exitMark.detach();

    for (std::thread* t : mThreads) {
        t->join();
    }


    for (std::thread* t : mThreads) {
        delete(t);
    }

    mThreads.clear();

    return 0;
}

